<?php 

    /**
     * This file is part of the Intelligencer package.
     * For the full copyright and license, please view the LICENSE
     * file that was distributed with this source code.
     * 
     * @author         Roman Drapeko <roman.drapeko@gmail.com>
     * @copyright      Roman Drapeko <roman.drapeko@gmail.com>, 2009 - present
     */

    /**
     * itScannerI implementation that is available to find the classes/interfaces in the particular files
     * 
     * @author drapeko
     * 
     */
    class itScanner implements itScannerI {
        
        /**
         * (non-PHPdoc)
         * @see Intelligencer/LibUtil/Scanner/itScannerI#scanFile($filePath)
         */
        public function scanFile($path) {
            $defaultNamespace = null;
            $result = new itScannerResult();
            
            if (is_readable($path)) {
                $path = itUtil::getRealPath($path);
                $tokens = token_get_all(php_strip_whitespace($path));
                
                $currentNamespace = $defaultNamespace;
                
                $lookForClassName = false;
                $lookForInterfaceName = false;
                $lookForNamespaceName = false;
                
                for ($i = 0; $i < count($tokens); $i++) {
                    $t = $tokens[$i];
                    if (is_array($t) && isset($t[0])) {
                        $token_name = token_name($t[0]);
                        
                        if ($token_name == 'T_NAMESPACE') {
                            $lookForNamespaceName = true;
                        } elseif (in_array($token_name, array('T_CLASS', 'T_INTERFACE'))) {
                            if ($lookForNamespaceName) {
                                $currentNamespace = $defaultNamespace;
                                $lookForNamespaceName = false;
                            }
                            
                            if (!$lookForClassName && !$lookForInterfaceName) {
                                // if it found class or interface without the namespacename it means that the namespace is default
                                $lookForNamespaceName = false;
                                if ($token_name == 'T_CLASS') {
                                    $lookForClassName = true;
                                } elseif ($token_name == 'T_INTERFACE') {
                                    $lookForInterfaceName = true;
                                }
                            }
                        } elseif ($token_name == 'T_STRING') {
                            if ($lookForClassName) {
                                $result->setClass(array($currentNamespace, $t[1]), $path);
                                $lookForClassName = false;
                            } elseif ($lookForInterfaceName) {
                                $result->setInterface(array($currentNamespace, $t[1]), $path);
                                $lookForInterfaceName = false;                   
                            } elseif ($lookForNamespaceName) {
                                $currentNamespace = strtolower($t[1]);
                                // look for the rest of the string
                                while(true) {
                                    if (!array_key_exists($i + 1, $tokens)) {
                                        break;
                                    }
                                    $nextToken = $tokens[$i + 1];
                                    if (!is_array($nextToken) || !isset($nextToken[0])) {
                                        break;
                                    }
                                    $nextTokenName = token_name($nextToken[0]);
                                    if (!in_array($nextTokenName, array('T_STRING', 'T_NS_SEPARATOR'))) {
                                        break;
                                    } else {
                                        $currentNamespace .= strtolower($nextToken[1]);
                                        $i++;
                                    }
                                }
    
                                $lookForNamespaceName = false;
                            }
                        } 
                    }
                }
                
            } else {
                throw new itException("Invalid file passed to scanFile: $path");
            }
    
            return $result;
        }
    }

?>